package oceanlife;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import java.util.Random;
import java.util.UUID;

import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.SwingWorker;

import oceanlife.evostrat.Gene;
import oceanlife.evostrat.GeneCrossing;
import oceanlife.evostrat.GenePillarHallway;
import oceanlife.log.ImageDrawer;
import oceanlife.log.Logger;
import oceanlife.pathfinding.Obstacles;
import oceanlife.pathfinding.Pnt;



import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class Starter {

	public static JFrame f = new JFrame();
	public static ArrayList<SimpleSimPanel> envs = new ArrayList<SimpleSimPanel>();
	public static int panelXSize;
	public static int panelYSize;
	public static JButton startButton;
	public static JButton seedButton;
	public static JButton pauzeButton;
	public static JButton stopButton;
	public static JButton playbackButton;
	public static JButton checkFitnessButton;
	public static JButton printSolutionButton;
	public static JLabel infoLabel;
	public static JLabel seedLabel;
	public static JTextField childrenField;
	public static JTextField spawnIntervalField;
	public static JTextField scenarioCountField;
	public static JTextField maxCyclesField;
	public static JTextField seedField;
	public static JTextField playbackField;
	public static JTextField GenesField;
	public static JTextField PictureTextField;
	public static JCheckBox posLoggingBox;
	public static String testSet = "Straight";//Crossing,Straight
	private static int Xtest1 = 225;
	private static int Ytest1 = 225;
	private static int corLength = 40;

	private static void readBoxes(ArrayList<AgentCustomSettings> agentSpawns){
    	OLSet.setInt("children",Integer.parseInt(childrenField.getText()));
    	OLSet.setInt("spawnInterval",Integer.parseInt(spawnIntervalField.getText()));
    	OLSet.setInt("scenarioCount",Integer.parseInt(scenarioCountField.getText()));
    	OLSet.setInt("maxCycles",Integer.parseInt(maxCyclesField.getText()));
		int agentsPerScenario = 0;
		for(AgentCustomSettings agentSpawn : agentSpawns){
			agentsPerScenario += Integer.parseInt(agentSpawn.agNum.getText());
		}
		OLSet.setInt("agentsPerScenario", agentsPerScenario);



	}
	
	private static void start(ArrayList<AgentCustomSettings> agentSpawns){
    	for(SimpleSimPanel env : envs){
    		f.remove(env);
    	}
    	envs.clear();
    	readBoxes(agentSpawns);
    	setPanelSizes();
    	for(SimpleSimPanel env : envs){
			f.getContentPane().add(env);
		}

		f.setPreferredSize(new Dimension(panelXSize+300,panelYSize+90));
 	
	}
	
	public static Gene fitnessCheck(ArrayList<AgentCustomSettings> agentSpawns){
		String text = GenesField.getText();
		boolean scenarioDetermained = false;
		ArrayList<Double> geneValues = new ArrayList<Double>();
		for(String piece : text.split(" ")){
			if(piece.equals("Gene:") || piece.length() < 2){
				continue;
			}
			if(piece.length() > 1){
				if(!scenarioDetermained){
					if(piece.split(":")[0].equals("Y")){
						OLSet.set("testSet","Straight");
						scenarioDetermained = true;
					}
					if(piece.split(":")[0].equals("X")){
						OLSet.set("testSet","Crossing");
						scenarioDetermained = true;
					}
				}
				geneValues.add(Double.parseDouble(piece.split(":")[1]));	
			}
		}
		Gene gene = null;
		if(OLSet.get("testSet").equals("Straight")){
			gene = GenePillarHallway.getInitChild();
		}
		if(OLSet.get("testSet").equals("Crossing")){
			gene = GeneCrossing.getInitChild();
		}
		double[] geneValuesD = new double[geneValues.size()];
		for(int i = 0; i < geneValues.size();i++){
			geneValuesD[i] = geneValues.get(i);
		}
		gene.setGenes(geneValuesD);
		start(agentSpawns);
		return gene;
	}
	
	public static BufferedReader playback(){
		try{
	    	for(SimpleSimPanel env : envs){
	    		f.remove(env);
	    	}
	    	envs.clear();
	    	String playbackFilename = playbackField.getText();
	    	FileReader fstream = new FileReader("playbacklogs\\"+playbackFilename);
	    	BufferedReader poslog = new BufferedReader(fstream);
			String[] initInfo = poslog.readLine().split(" ");
			
			OLSet.set("testSet",initInfo[1]);
	    	OLSet.setInt("children",1);
	    	OLSet.setInt("spawnInterval",Integer.parseInt(initInfo[2]));
	    	
	    	int teller = 0;
	    	double[] geneValues = new double[initInfo.length-3/3];
	    	while((teller*3)+3 < initInfo.length){
	    		geneValues[teller*2]= Double.parseDouble(initInfo[teller*3+4].split(":")[1]);
	    		geneValues[teller*2+1]= Double.parseDouble(initInfo[teller*3+5].split(":")[1]);
	    		teller++;
	    	}
			Gene gene = null;
			if(OLSet.get("testSet").equals("Straight")){
				gene = GenePillarHallway.getInitChild();
			}
			if(OLSet.get("testSet").equals("Crossing")){
				gene = GeneCrossing.getInitChild();
			}
			gene.setGenes(geneValues);
	    	
			setPanelSizes();
			
			for(SimpleSimPanel env : envs){
				env.readGenesPlayback(gene);
				f.getContentPane().add(env);
			}
	
			f.setPreferredSize(new Dimension(panelXSize+300,panelYSize+90));
			return poslog;
	 	
		} catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}
	
	private static void setPanelSizes() {
		int childXSize = 0;
		int childYSize = 0;
		if(OLSet.get("testSet").equals("Straight")){
			childXSize = 450;
			childYSize = 120;
			panelXSize = childXSize*2;
			panelYSize = childYSize*((OLSet.getInt("children")+1)/2);
			for(int i = 0; i < OLSet.getInt("children");i++){
				envs.add(new SimpleSimPanel(OLSet.getInt("children")));
				envs.get(i).setBounds(0+(i%2)*childXSize, (i/2)*childYSize, childXSize, childYSize);
			}
		}
		if(OLSet.get("testSet").equals("Crossing")){
			childXSize = Xtest1;
			childYSize = Ytest1;
			panelXSize = childXSize*(900/Xtest1);
			panelYSize = childYSize*((OLSet.getInt("children")+(900/Xtest1-1))/(900/Xtest1));
			for(int i = 0; i < OLSet.getInt("children");i++){
				envs.add(new SimpleSimPanel(OLSet.getInt("children")));
				envs.get(i).setBounds(0+(i%(900/Xtest1))*childXSize, (i/(900/Xtest1))*childYSize, childXSize, childYSize);
			}
		}
		if(panelYSize < 400){
			panelYSize = 500;
		}
	}

	public static void main(String[] args) {
		//Integer children = 10;

		RandomGen.setSeed(new Random().nextLong());
    	OLSet.set("testSet",testSet);
    	OLSet.setInt("PosLogging",0);
		
		startButton = new JButton("Start");
		pauzeButton = new JButton("Pauze");
		stopButton = new JButton("Stop");
		seedButton = new JButton("Seed");
		playbackButton = new JButton("Playback");
		checkFitnessButton = new JButton("Check Fitness");
		printSolutionButton = new JButton("Print Solution");
		infoLabel = new JLabel("No results yet");
		seedLabel = new JLabel(Long.toString(RandomGen.getSeed()));
		childrenField = new JTextField("1");
		spawnIntervalField = new JTextField("100");
		scenarioCountField = new JTextField("3");
		maxCyclesField = new JTextField("30000");
		seedField = new JTextField("0");
		playbackField = new JTextField();
		GenesField = new JTextField();
		PictureTextField = new JTextField();
		posLoggingBox = new JCheckBox("Logging");
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		start(new ArrayList<AgentCustomSettings>());
		OLSet.setInt("stopping", 0);
		OLSet.setInt("pauze", 0);
		f.getContentPane().setLayout(null);
		//final JComboBox obstacleSetList = new JComboBox(OLSet.getObstacleSets());
		//obstacleSetList.setBounds(panelXSize+100, 50, 40, 20);
        
		startButton.setBounds(panelXSize+180, 15, 80, 20);
		pauzeButton.setBounds(panelXSize+180, 40, 80, 20);
		stopButton.setBounds(panelXSize+180, 65, 80, 20);
		seedButton.setBounds(panelXSize+10, 125, 70, 40);
		playbackButton.setBounds(panelXSize+180, 175, 80, 20);
		playbackButton.setMargin(new Insets(1, 1, 1, 1) ); 
		checkFitnessButton.setBounds(panelXSize+10, 227, 120, 20);
		checkFitnessButton.setMargin(new Insets(1, 1, 1, 1) ); 
		printSolutionButton.setBounds(panelXSize+140, 227, 120, 20);
		printSolutionButton.setMargin(new Insets(1, 1, 1, 1) ); 

		infoLabel.setBounds(panelXSize+10, 10, 150, 20);
		seedLabel.setBounds(panelXSize+90, 125, 150, 18);
		seedField.setBounds(panelXSize+90, 145, 150, 18);
		playbackField.setBounds(panelXSize+10, 177, 160, 18);
		GenesField.setBounds(panelXSize+10, 207, 250, 18);
		PictureTextField.setBounds(panelXSize+140, 250, 120, 18);
		posLoggingBox.setBounds(panelXSize+185, 90, 150, 18);
		
		JLabel childrenLabel = new JLabel("Children");
		childrenLabel.setBounds(panelXSize+70, 38, 300, 20);
		childrenField.setBounds(panelXSize+10, 40, 50, 18);
		JLabel spawnIntervalLabel = new JLabel("Spawn Interval");
		spawnIntervalLabel.setBounds(panelXSize+70, 58, 300, 20);
		spawnIntervalField.setBounds(panelXSize+10, 60, 50, 18);
		JLabel scenarioCountLabel = new JLabel("Scenario Count");
		scenarioCountLabel.setBounds(panelXSize+70, 78, 300, 20);
		scenarioCountField.setBounds(panelXSize+10, 80, 50, 18);
		JLabel maxCyclesLabel = new JLabel("Max Cycles");
		maxCyclesLabel.setBounds(panelXSize+70, 98, 300, 20);
		maxCyclesField.setBounds(panelXSize+10, 100, 50, 18);
		
		
		//agent settings
		int xOffset = panelXSize + 5;
		int yOffset = 320;
		int interSpacing = 60;
		
		//headers
		JLabel header = new JLabel("Agents:");
		header.setBounds(xOffset+90, yOffset-40, 300, 15);
		f.getContentPane().add(header);
		JLabel header2 = new JLabel("Use         Start Box        Number    Goal");
		header2.setBounds(xOffset, yOffset-20, 300, 15);
		f.getContentPane().add(header2);
		
		final ArrayList<AgentCustomSettings> agentSpawns = new ArrayList<AgentCustomSettings>();
		
		if(OLSet.get("testSet").equals("Straight")){
			for(int i = 0; i < 2;i++){
				AgentCustomSettings agentSpawn = new AgentCustomSettings(f.getContentPane());
				agentSpawn.setDimensions(i,xOffset,yOffset,interSpacing);
				if(i==0){
					agentSpawn.setValues(true,"450","20","500","100","30","-1000","60");
				}
				if(i==1){
					agentSpawn.setValues(true,"-50","20","0","100","30","1450","60");
				}
				agentSpawns.add(agentSpawn);
			}
		}
		if(OLSet.get("testSet").equals("Crossing")){
			for(int i = 0; i < 4;i++){
				int middleXSc = Xtest1/2;
				int middleYSc = Ytest1/2;
				AgentCustomSettings agentSpawn = new AgentCustomSettings(f.getContentPane());
				agentSpawn.setDimensions(i,xOffset,yOffset,interSpacing);
				if(i==0){
					agentSpawn.setValues(true,
							Integer.toString(middleXSc*2),
							Integer.toString(0+(corLength+10)),
							Integer.toString(middleXSc*2+100),
							Integer.toString(middleYSc*2-(corLength+10)),
							"10",
							Integer.toString(0-1000),
							Integer.toString(middleYSc));
				}
				if(i==1){
					agentSpawn.setValues(true,
							Integer.toString(0-100),
							Integer.toString(0+(corLength+10)),
							Integer.toString(0),
							Integer.toString(middleYSc*2-(corLength+10)),
							"10",
							Integer.toString(middleXSc*2+1000),
							Integer.toString(middleYSc));
				}
				if(i==2){
					agentSpawn.setValues(true,
							Integer.toString(0+(corLength+10)),
							Integer.toString(0-100),
							Integer.toString(middleXSc*2-(corLength+10)),
							Integer.toString(0),
							"10",
							Integer.toString(middleXSc),
							Integer.toString(middleYSc*2+1000));
				}
				if(i==3){
					agentSpawn.setValues(true,
							Integer.toString(0+(corLength+10)),
							Integer.toString(middleYSc*2),
							Integer.toString(middleXSc*2-(corLength+10)),
							Integer.toString(middleYSc*2+100),
							"10",
							Integer.toString(middleXSc),
							Integer.toString(0-1000));
				}
				agentSpawns.add(agentSpawn);
			}
		}

		
		
		seedButton.addActionListener(new ActionListener() {
	        public void actionPerformed(ActionEvent e)
	        {
	        	RandomGen.setSeed(Long.parseLong(seedField.getText()));
	        	seedLabel.setText(Long.toString(RandomGen.getSeed()));
	        }
		});
		startButton.addActionListener(new ActionListener() {
	        public void actionPerformed(ActionEvent e)
	        {
	        	seedButton.setEnabled(false);
	        	start(agentSpawns);
	    		f.pack();
	            f.repaint();

                OLSet.setInt("stopping", 0);
	        	new GenStarterWorker(envs,agentSpawns,infoLabel).execute();
	        }
		});
		pauzeButton.addActionListener(new ActionListener() {
	        public void actionPerformed(ActionEvent e)
	        {
    			Date dateNow = new Date ();
    			SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd 'at' HH:mm:ss z");
    			StringBuilder dateString = new StringBuilder( sdf.format( dateNow ) );
	        	if(OLSet.getInt("pauze") == 0){
	        		OLSet.setInt("pauze", 1);
	    			Logger.write("pauzed at:");
	    			Logger.write(dateString.toString());

	        	} else {
	        		OLSet.setInt("pauze", 0);
	    			Logger.write("resumed at:");
	    			Logger.write(dateString.toString());
	        	}
	        }
		});
		stopButton.addActionListener(new ActionListener() {
	        public void actionPerformed(ActionEvent e)
	        {
                OLSet.setInt("stopping", 1);
	        }
		});
		posLoggingBox.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if(posLoggingBox.isSelected()){
			    	OLSet.setInt("PosLogging",1);
				} else {
			    	OLSet.setInt("PosLogging",0);
				}
				
				
			}
		});
		playbackButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
	        	BufferedReader poslog = playback();
	    		f.pack();
	            f.repaint();

                OLSet.setInt("stopping", 0);
	        	new PlaybackWorker(envs.get(0),infoLabel,poslog).execute();
				
			}
		});
		checkFitnessButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				int[] intervals = new int[]{500,250,150,100,50,25,1};
				for(int interval : intervals){
		        	seedButton.setEnabled(false);
					Gene gene = fitnessCheck(agentSpawns);
		    		f.pack();
		            f.repaint();
	
		            OLSet.setInt("spawnInterval", interval);
	                OLSet.setInt("stopping", 0);
		        	FitnessCheckWorker worker = new FitnessCheckWorker(envs,agentSpawns,infoLabel,gene);
		        	worker.execute();
		        	while(!worker.isDone()){
		        		try {
							Thread.sleep(100);
						} catch (InterruptedException e1) {
							e1.printStackTrace();
						}
		        	}
				}
			}
		});
		printSolutionButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Gene gene = fitnessCheck(agentSpawns);
	    		f.pack();
	            f.repaint();

                OLSet.setInt("stopping", 0);
                ArrayList<Double> values = new ArrayList<Double>();
                for(double value : gene.getGenes()){
                	values.add(value);
                }
                new ImageDrawer(values, OLSet.get("testSet"), UUID.randomUUID().toString(),PictureTextField.getText());
			}
		});
        f.getContentPane().add(startButton);
        f.getContentPane().add(pauzeButton);
        f.getContentPane().add(stopButton);
        f.getContentPane().add(seedButton);
        f.getContentPane().add(playbackButton);
        f.getContentPane().add(checkFitnessButton);
        f.getContentPane().add(printSolutionButton);
		f.getContentPane().add(childrenLabel);
		f.getContentPane().add(spawnIntervalLabel);
		f.getContentPane().add(scenarioCountLabel);
		f.getContentPane().add(maxCyclesLabel);
		f.getContentPane().add(infoLabel);
		f.getContentPane().add(seedLabel);
		f.getContentPane().add(childrenField);
		f.getContentPane().add(spawnIntervalField);
		f.getContentPane().add(scenarioCountField);
		f.getContentPane().add(maxCyclesField);
		f.getContentPane().add(seedField);
		f.getContentPane().add(playbackField);
		f.getContentPane().add(GenesField);
		f.getContentPane().add(PictureTextField);
		f.getContentPane().add(posLoggingBox);
        f.pack();
        f.setVisible(true);

	
	}

}
